using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using ActiproSoftware.ComponentModel;
using ActiproSoftware.SyntaxEditor;

namespace WindowsUserControl.Codes {

	/// <summary>
	/// Represents a form for selection a line to go to.
	/// </summary>
	public class StyleEditorForm : System.Windows.Forms.Form {

		private SyntaxEditor				editor;
		private HighlightingStyle[][]		highlightingStyles;
		private bool						ignoreUpdateRequest;
		private SyntaxLanguageCollection	languages;
		private HighlightingStyle			selectedHighlightingStyle;
		
		//

		private System.Windows.Forms.Label backColorLabel;
		private System.Windows.Forms.Label foreColorLabel;
		private System.Windows.Forms.CheckBox boldCheckBox;
		private System.Windows.Forms.Button okButton;
		private System.Windows.Forms.Button cancelButton;
		private System.Windows.Forms.ListBox styleListBox;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.ComboBox languageDropDownList;
		private System.Windows.Forms.CheckBox italicCheckBox;
		private ColorButton backColorButton;
		private ColorButton foreColorButton;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.CheckBox underlineCheckBox;
		private ActiproSoftware.SyntaxEditor.TextStylePreview sampleLabel;
		private ComboBox defaultFontSizeComboBox;
		private Label label1;
		private FontDropDownList defaultFontFaceComboBox;
		private Label label4;
		private Label label5;
	
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="editor"></param>
		public StyleEditorForm(SyntaxEditor editor) {
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// Add any constructor code after InitializeComponent call
			//
			this.editor = editor;

			// Get the default font 
			defaultFontFaceComboBox.SelectedIndex = defaultFontFaceComboBox.FindStringExact(editor.Font.Name);
			defaultFontSizeComboBox.SelectedIndex = defaultFontSizeComboBox.FindStringExact(Math.Round(editor.Font.SizeInPoints).ToString());

			// Get a collection of all the language that are currently loaded
			languages = SyntaxLanguage.GetLanguageCollection(editor.Document.Language);

			// Create an array to hold highlighting styles
			highlightingStyles = new HighlightingStyle[languages.Count][];

			// Loop through each language
			for (int languageIndex = 0; languageIndex < languages.Count; languageIndex++) {
				// Load the language drop down
				SyntaxLanguage language = languages[languageIndex];
				languageDropDownList.Items.Add(language.Key);

				// Update the highlighting style array and create clones of each higlighting style
				highlightingStyles[languageIndex] = new HighlightingStyle[language.HighlightingStyles.Count];
				for (int highlightingStyleIndex = 0; highlightingStyleIndex < language.HighlightingStyles.Count; highlightingStyleIndex++) {
					highlightingStyles[languageIndex][highlightingStyleIndex] = language.HighlightingStyles[highlightingStyleIndex].Clone();
				}
			}
			languageDropDownList.SelectedIndex = 0;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing) {
			if (disposing) {
				if (components != null) 
					components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.backColorButton = new ColorButton();
			this.foreColorButton = new ColorButton();
			this.backColorLabel = new System.Windows.Forms.Label();
			this.foreColorLabel = new System.Windows.Forms.Label();
			this.boldCheckBox = new System.Windows.Forms.CheckBox();
			this.italicCheckBox = new System.Windows.Forms.CheckBox();
			this.okButton = new System.Windows.Forms.Button();
			this.cancelButton = new System.Windows.Forms.Button();
			this.sampleLabel = new ActiproSoftware.SyntaxEditor.TextStylePreview();
			this.styleListBox = new System.Windows.Forms.ListBox();
			this.label2 = new System.Windows.Forms.Label();
			this.languageDropDownList = new System.Windows.Forms.ComboBox();
			this.label3 = new System.Windows.Forms.Label();
			this.underlineCheckBox = new System.Windows.Forms.CheckBox();
			this.defaultFontSizeComboBox = new System.Windows.Forms.ComboBox();
			this.label1 = new System.Windows.Forms.Label();
			this.defaultFontFaceComboBox = new ActiproSoftware.SyntaxEditor.FontDropDownList();
			this.label4 = new System.Windows.Forms.Label();
			this.label5 = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// backColorButton
			// 
			this.backColorButton.BackColor = System.Drawing.SystemColors.Window;
			this.backColorButton.Color = System.Drawing.Color.Brown;
			this.backColorButton.Location = new System.Drawing.Point(202, 151);
			this.backColorButton.Name = "backColorButton";
			this.backColorButton.Size = new System.Drawing.Size(112, 21);
			this.backColorButton.TabIndex = 5;
			this.backColorButton.ColorChanged += new System.EventHandler(this.backColorButton_ColorChanged);
			// 
			// foreColorButton
			// 
			this.foreColorButton.BackColor = System.Drawing.SystemColors.Window;
			this.foreColorButton.Color = System.Drawing.Color.IndianRed;
			this.foreColorButton.Location = new System.Drawing.Point(202, 103);
			this.foreColorButton.Name = "foreColorButton";
			this.foreColorButton.Size = new System.Drawing.Size(112, 21);
			this.foreColorButton.TabIndex = 4;
			this.foreColorButton.ColorChanged += new System.EventHandler(this.foreColorButton_ColorChanged);
			// 
			// backColorLabel
			// 
			this.backColorLabel.AutoSize = true;
			this.backColorLabel.Location = new System.Drawing.Point(199, 135);
			this.backColorLabel.Name = "backColorLabel";
			this.backColorLabel.Size = new System.Drawing.Size(90, 13);
			this.backColorLabel.TabIndex = 4;
			this.backColorLabel.Text = "Item background:";
			// 
			// foreColorLabel
			// 
			this.foreColorLabel.AutoSize = true;
			this.foreColorLabel.Location = new System.Drawing.Point(199, 87);
			this.foreColorLabel.Name = "foreColorLabel";
			this.foreColorLabel.Size = new System.Drawing.Size(84, 13);
			this.foreColorLabel.TabIndex = 5;
			this.foreColorLabel.Text = "Item foreground:";
			// 
			// boldCheckBox
			// 
			this.boldCheckBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.boldCheckBox.Location = new System.Drawing.Point(202, 183);
			this.boldCheckBox.Name = "boldCheckBox";
			this.boldCheckBox.Size = new System.Drawing.Size(52, 24);
			this.boldCheckBox.TabIndex = 6;
			this.boldCheckBox.Text = "Bold";
			this.boldCheckBox.CheckedChanged += new System.EventHandler(this.boldCheckBox_CheckedChanged);
			// 
			// italicCheckBox
			// 
			this.italicCheckBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.italicCheckBox.Location = new System.Drawing.Point(260, 183);
			this.italicCheckBox.Name = "italicCheckBox";
			this.italicCheckBox.Size = new System.Drawing.Size(54, 24);
			this.italicCheckBox.TabIndex = 7;
			this.italicCheckBox.Text = "Italic";
			this.italicCheckBox.CheckedChanged += new System.EventHandler(this.italicCheckBox_CheckedChanged);
			// 
			// okButton
			// 
			this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
			this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
			this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.okButton.Location = new System.Drawing.Point(247, 299);
			this.okButton.Name = "okButton";
			this.okButton.Size = new System.Drawing.Size(75, 23);
			this.okButton.TabIndex = 100;
			this.okButton.Text = "OK";
			this.okButton.Click += new System.EventHandler(this.okButton_Click);
			// 
			// cancelButton
			// 
			this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
			this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.cancelButton.Location = new System.Drawing.Point(327, 299);
			this.cancelButton.Name = "cancelButton";
			this.cancelButton.Size = new System.Drawing.Size(75, 23);
			this.cancelButton.TabIndex = 101;
			this.cancelButton.Text = "Cancel";
			// 
			// sampleLabel
			// 
			this.sampleLabel.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.sampleLabel.Location = new System.Drawing.Point(202, 233);
			this.sampleLabel.Name = "sampleLabel";
			this.sampleLabel.Size = new System.Drawing.Size(199, 56);
			this.sampleLabel.TabIndex = 11;
			// 
			// styleListBox
			// 
			this.styleListBox.DisplayMember = "Name";
			this.styleListBox.Location = new System.Drawing.Point(9, 103);
			this.styleListBox.Name = "styleListBox";
			this.styleListBox.Size = new System.Drawing.Size(184, 186);
			this.styleListBox.TabIndex = 3;
			this.styleListBox.SelectedIndexChanged += new System.EventHandler(this.styleListBox_SelectedIndexChanged);
			// 
			// label2
			// 
			this.label2.AutoSize = true;
			this.label2.Location = new System.Drawing.Point(6, 87);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(71, 13);
			this.label2.TabIndex = 13;
			this.label2.Text = "Display items:";
			// 
			// languageDropDownList
			// 
			this.languageDropDownList.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.languageDropDownList.Location = new System.Drawing.Point(69, 10);
			this.languageDropDownList.Name = "languageDropDownList";
			this.languageDropDownList.Size = new System.Drawing.Size(245, 21);
			this.languageDropDownList.TabIndex = 0;
			this.languageDropDownList.SelectedIndexChanged += new System.EventHandler(this.languageDropDownList_SelectedIndexChanged);
			// 
			// label3
			// 
			this.label3.AutoSize = true;
			this.label3.Location = new System.Drawing.Point(6, 13);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(60, 13);
			this.label3.TabIndex = 14;
			this.label3.Text = "Languages";
			// 
			// underlineCheckBox
			// 
			this.underlineCheckBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.underlineCheckBox.Location = new System.Drawing.Point(319, 183);
			this.underlineCheckBox.Name = "underlineCheckBox";
			this.underlineCheckBox.Size = new System.Drawing.Size(65, 24);
			this.underlineCheckBox.TabIndex = 8;
			this.underlineCheckBox.Text = "Underline";
			this.underlineCheckBox.CheckedChanged += new System.EventHandler(this.underlineCheckBox_CheckedChanged);
			// 
			// defaultFontSizeComboBox
			// 
			this.defaultFontSizeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.defaultFontSizeComboBox.Items.AddRange(new object[] {
            "6",
            "7",
            "8",
            "9",
            "10",
            "11",
            "12",
            "13",
            "14",
            "15",
            "16",
            "17",
            "18",
            "19",
            "20",
            "21",
            "22",
            "23",
            "24",
            "25",
            "26"});
			this.defaultFontSizeComboBox.Location = new System.Drawing.Point(324, 56);
			this.defaultFontSizeComboBox.Name = "defaultFontSizeComboBox";
			this.defaultFontSizeComboBox.Size = new System.Drawing.Size(78, 21);
			this.defaultFontSizeComboBox.TabIndex = 2;
			this.defaultFontSizeComboBox.SelectedIndexChanged += new System.EventHandler(this.fontComboBox_SelectedIndexChanged);
			// 
			// label1
			// 
			this.label1.AutoSize = true;
			this.label1.Location = new System.Drawing.Point(6, 40);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(207, 13);
			this.label1.TabIndex = 112;
			this.label1.Text = "Font (bold type indicates fixed-width fonts):";
			// 
			// defaultFontFaceComboBox
			// 
			this.defaultFontFaceComboBox.Location = new System.Drawing.Point(9, 56);
			this.defaultFontFaceComboBox.Name = "defaultFontFaceComboBox";
			this.defaultFontFaceComboBox.Size = new System.Drawing.Size(305, 21);
			this.defaultFontFaceComboBox.TabIndex = 1;
			this.defaultFontFaceComboBox.SelectedIndexChanged += new System.EventHandler(this.fontComboBox_SelectedIndexChanged);
			// 
			// label4
			// 
			this.label4.AutoSize = true;
			this.label4.Location = new System.Drawing.Point(321, 40);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(30, 13);
			this.label4.TabIndex = 113;
			this.label4.Text = "Size:";
			// 
			// label5
			// 
			this.label5.AutoSize = true;
			this.label5.Location = new System.Drawing.Point(199, 217);
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size(45, 13);
			this.label5.TabIndex = 114;
			this.label5.Text = "Sample:";
			// 
			// StyleEditorForm
			// 
			this.AcceptButton = this.okButton;
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.CancelButton = this.cancelButton;
			this.ClientSize = new System.Drawing.Size(409, 329);
			this.Controls.Add(this.defaultFontSizeComboBox);
			this.Controls.Add(this.defaultFontFaceComboBox);
			this.Controls.Add(this.underlineCheckBox);
			this.Controls.Add(this.italicCheckBox);
			this.Controls.Add(this.languageDropDownList);
			this.Controls.Add(this.styleListBox);
			this.Controls.Add(this.sampleLabel);
			this.Controls.Add(this.okButton);
			this.Controls.Add(this.cancelButton);
			this.Controls.Add(this.boldCheckBox);
			this.Controls.Add(this.foreColorButton);
			this.Controls.Add(this.backColorButton);
			this.Controls.Add(this.label4);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.label3);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.foreColorLabel);
			this.Controls.Add(this.backColorLabel);
			this.Controls.Add(this.label5);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
			this.MaximizeBox = false;
			this.MinimizeBox = false;
			this.Name = "StyleEditorForm";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Highlighting Style Editor";
			this.ResumeLayout(false);
			this.PerformLayout();

		}
		#endregion

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// EVENT HANDLERS
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Occurs when the color of the <see cref="ColorButton"/> is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void backColorButton_ColorChanged(object sender, EventArgs e) {
			this.UpdateHighlightingStyle();
		}

		/// <summary>
		/// Occurs when the checked state of the <see cref="CheckBox"/> is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void boldCheckBox_CheckedChanged(object sender, System.EventArgs e) {
			this.UpdateHighlightingStyle();
		}
		
		/// <summary>
		/// Occurs when the selected index is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void fontComboBox_SelectedIndexChanged(object sender, EventArgs e) {
			if ((defaultFontFaceComboBox.SelectedItem != null) && (defaultFontSizeComboBox.SelectedItem != null))
				sampleLabel.Font = new Font(((FontDropDownList.FontFamilyData)defaultFontFaceComboBox.SelectedItem).Name, Convert.ToSingle(defaultFontSizeComboBox.SelectedItem));
		}

		/// <summary>
		/// Occurs when the color of the <see cref="ColorButton"/> is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void foreColorButton_ColorChanged(object sender, EventArgs e) {
			this.UpdateHighlightingStyle();
		}

		/// <summary>
		/// Occurs when the checked state of the <see cref="CheckBox"/> is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void italicCheckBox_CheckedChanged(object sender, System.EventArgs e) {
			this.UpdateHighlightingStyle();
		}

		/// <summary>
		/// Occurs when the checked state of the <see cref="CheckBox"/> is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void underlineCheckBox_CheckedChanged(object sender, System.EventArgs e) {
			this.UpdateHighlightingStyle();
		}

		/// <summary>
		/// Occurs when the selected index is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void languageDropDownList_SelectedIndexChanged(object sender, System.EventArgs e) {
			this.LoadLanguage(languageDropDownList.SelectedIndex);
		}

		/// <summary>
		/// Occurs when the selected index is changed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void okButton_Click(object sender, System.EventArgs e) {
			// Mark for batch update
			editor.Document.Language.IsUpdating = true;

			// Loop through each language and update the highlighting styles
			for (int languageIndex = 0; languageIndex < languages.Count; languageIndex++) {
				foreach (HighlightingStyle highlightingStyle in highlightingStyles[languageIndex]) {
					languages[languageIndex].HighlightingStyles.Add(highlightingStyle);					
				}
			}

			// Mark batch update complete
			editor.Document.Language.IsUpdating = false;

			// Update the font
			editor.Font = sampleLabel.Font;
		}

		/// <summary>
		/// Occurs when the button is pressed.
		/// </summary>
		/// <param name="sender">Sender of the event.</param>
		/// <param name="e">Event arguments.</param>
		private void styleListBox_SelectedIndexChanged(object sender, System.EventArgs e) {
			this.UpdateHighlightingStyle();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// NON-PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Loads the highlighting styles from the specified language into the editor.
		/// </summary>
		/// <param name="index">The index of the language to load.</param>
		private void LoadLanguage(int index) {
			selectedHighlightingStyle = null;

			styleListBox.Items.Clear();
			foreach (HighlightingStyle highlightingStyle in highlightingStyles[index]) {
				styleListBox.Items.Add(highlightingStyle);
			}

			styleListBox.SelectedIndex = 0;
		}

		/// <summary>
		/// Updates the selected style with the current settings and updates the controls.
		/// </summary>
		private void UpdateHighlightingStyle() {
			if (ignoreUpdateRequest)
				return;

			// Update old selected style
			if (selectedHighlightingStyle != null) {
				selectedHighlightingStyle.ForeColor = foreColorButton.Color;
				selectedHighlightingStyle.BackColor = backColorButton.Color;
				selectedHighlightingStyle.Bold = (boldCheckBox.Checked ? DefaultableBoolean.True : DefaultableBoolean.Default);
				selectedHighlightingStyle.Italic = (italicCheckBox.Checked ? DefaultableBoolean.True : DefaultableBoolean.Default);
				selectedHighlightingStyle.UnderlineStyle = (underlineCheckBox.Checked ? HighlightingStyleLineStyle.Solid : HighlightingStyleLineStyle.Default);
			}

			if (styleListBox.SelectedIndex == -1)
				return;

			ignoreUpdateRequest = true;
			
			// Update controls
			selectedHighlightingStyle = (HighlightingStyle)styleListBox.SelectedItem;
			foreColorButton.Color = selectedHighlightingStyle.ForeColor;
			backColorButton.Color = selectedHighlightingStyle.BackColor;
			boldCheckBox.Checked = (selectedHighlightingStyle.Bold == DefaultableBoolean.True);
			italicCheckBox.Checked = (selectedHighlightingStyle.Italic == DefaultableBoolean.True);
			underlineCheckBox.Checked = (selectedHighlightingStyle.UnderlineStyle == HighlightingStyleLineStyle.Solid);

			// Update sample label
			sampleLabel.HighlightingStyle = selectedHighlightingStyle;

			ignoreUpdateRequest = false;
		}

	}
}
